<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>

</html>
<script>

    // // 1.在js中如何实现一个类
    // function Person() {
    //     this.name = "jack";
    //     this.age = 100;

    //     this.run = function () {
    //         alert("hello world");
    //     }
    // }
    // // 实例化的对象
    // let person = new Person();
    // console.log(person.name);
    // console.log(person.age);
    // person.run();

    // function Person(){
    //     this.name="jack";
    //     this.age="100";
    //     this.run=function(){
    //         alert("hello world");
    //     }
    // }
    // let person=new Person();
    // console.log(person.name);
    // console.log(person.age);
    // person.run();

    // function Person(){
    //     this.name="jack";
    //     this.age="100";
    //     this.run=function(){
    //         alert("hello world");
    //     }
    // }
    // let person=new Person();
    // console.log(person.name);
    // console.log(person.age);
    // person.run();

    // function Person(){
    //     this.name="jack";
    //     this.age="100";
    //     this.run=function(){
    //         alert("hello world");
    //     }
    // }
    // let person=new Person();
    // console.log(person.name);
    // console.log(person.age);
    // person.run();

    // function Person(){
    //     this.name="jack";
    //     this.age="100";
    //     this.run=function(){
    //         alert("hello world");
    //     }
    // }
    // let person=new Person();
    // console.log(person.name);
    // console.log(person.age);
    // person.run();




    // // 2.私有属性和方法   公有属性和方法
    // function Person(){
    //     this.leaver=5;
    //     this.name="John"
    // }
    // Person.prototype.name="hello";
    // Person.prototype.age=100;
    // Person.prototype.run=function(){
    //     alert(this.name+this.age);
    // }
    // let person=new Person();
    // console.log(person.leaver);
    // console.log(person.name);  // 先输入函数内部的name
    // console.log(person.age);
    // person.run();

    // function Person(){
    //     this.leaver=5;
    //     this.name="John";
    // }
    // Person.prototype.name="hello";
    // Person.prototype.age=100;
    // Person.prototype.run=function(){
    //     alert(this.name+this.age);
    // }
    // let person=new Person();
    // console.log(person.leaver);
    // console.log(person.name);  // 先输出函数内部的name
    // console.log(person.age);
    // person.run();

    // function Person(){
    //     this.leaver=5;
    //     this.name="John";
    // }
    // Person.prototype.name="hello";
    // Person.prototype.age=100;
    // Person.prototype.run=function(){
    //     alert(this.name+this.age);
    // }
    // let person=new Person();
    // console.log(person.leaver);
    // console.log(person.name);  // 先输出函数内部的name
    // console.log(person.age);
    // person.run();

    // function Person(){
    //     this.leaver=5;
    //     this.name="John";
    // }
    // Person.prototype.name="hello";
    // Person.prototype.age=100;
    // Person.prototype.run=function(){
    //     alert(this.name+this.age);
    // }
    // let person=new Person();
    // console.log(person.leaver);
    // console.log(person.name);
    // console.log(person.age);  // 先输出函数内部的name
    // person.run();

    // function Person(){
    //     this.leaver=5;
    //     this.name="John";
    // }
    // Person.prototype.name="hello";
    // Person.prototype.age=100;
    // Person.prototype.run=function(){
    //     alert(this.name+this.age);
    // }
    // let person=new Person();
    // console.log(person.leaver);
    // console.log(person.name);  // 先输出函数内部的name
    // console.log(person.age);
    // person.run();




    // 3.静态方法的定义

    // function Person(){
    //     this.name="John";
    // }
    // // 静态方法
    // Person.age="hello";
    // Person.run=function(){
    //     alert(this.name);
    // }
    // // 调用静态用法
    // console.log(Person.age);
    // Person.run();
    // let p = new Person();
    // console.log(p.name);

    // function Person(){
    //     this.name="John";
    // }
    // // 静态方法
    // Person.age="hello";
    // Person.run=function(){
    //     alert(this.name);
    // }
    // // 调用静态用法
    // console.log(Person.age);
    // Person.run();
    // let p = new Person();
    // console.log(p.name);

    // function Person(){
    //     this.name="John";
    // }
    // // 静态方法
    // Person.age="hello";
    // Person.run=function(){
    //     alert(this.name);
    // }
    // // 调用静态用法
    // console.log(Person.age);
    // Person.run();
    // let p = new Person();
    // console.log(p.name);

    // function Person(){
    //     this.name="John";
    // }
    // // 静态方法
    // Person.age="hello";
    // Person.run=function(){
    //     alert(this.name);
    // }
    // // 调用静态用法
    // console.log(Person.age);
    // Person.run();
    // let p = new Person();
    // console.log(p.name);

    // function Person(){
    //     this.name="John";
    // }
    // // 静态方法
    // Person.age="hello";
    // Person.run=function(){
    //     alert(this.name);
    // }
    // // 调用静态用法
    // console.log(Person.age);
    // Person.run();
    // let p = new Person();
    // console.log(p.name);




    // 4.在js中实现继承  // 无法继承父类原型上的属性和方法

    // function Parent(){
    //     this.house="恒大房子";
    //     this.car="大众cc";
    //     this.message=function(){
    //         alert("哈哈哈哈");
    //     }
    // }
    // Parent.prototype.sex="男";
    // Parent.prototype.work=function(){
    //     alert("我是做IT的");
    // }
    // let p = new Parent();

    // function Child(){
    //     Parent.call(this);
    // }
    // let c = new Child();
    // console.log(c.house);
    // console.log(c.car);
    // console.log(c.sex);  // 无法继承父类原型上的属性和方法
    // c.message();  // 无法继承父类原型上的属性和方法

    // function Parent(){
    //     this.house="恒大房子";
    //     this.car="大众cc";
    //     this.message=function(){
    //         alert("哈哈哈哈");
    //     }
    // }
    // Parent.prototype.sex="男";
    // Parent.prototype.work=function(){
    //     alert("我是做IT的");
    // }
    // let p = new Parent();

    // function Child(){
    //     Parent.call(this);
    // }
    // let c = new Child();
    // console.log(c.house);
    // console.log(c.car);
    // console.log(c.sex);  // 无法继承父类原型上的属性和方法
    // c.message();  // 无法继承父类原型上的属性和方法

    // function Parent(){
    //     this.house="恒大房子";
    //     this.car="大众cc";
    //     this.message=function(){
    //         alert("哈哈哈哈");
    //     }
    // }
    // Parent.prototype.sex="男";
    // Parent.prototype.work=function(){
    //     alert("我是做IT的");
    // }
    // let p = new Parent();

    // function Child(){
    //     Parent.call(this);
    // }
    // let c = new Child();
    // console.log(c.house);
    // console.log(c.car);
    // console.log(c.sex);  // 无法继承父类原型上的属性和方法
    // c.message();  // 无法继承父类原型上的属性和方法

    // function Parent(){
    //     this.house="恒大房子";
    //     this.car="大众cc";
    //     this.message=function(){
    //         alert("哈哈哈哈");
    //     }
    // }
    // Parent.prototype.sex="男";
    // Parent.prototype.work=function(){
    //     alert("我是做IT的");
    // }
    // let p = new Parent();

    // function Child(){
    //     Parent.call(this);
    // }
    // let c = new Child();
    // console.log(c.house);
    // console.log(c.car);
    // console.log(c.sex);  // 无法继承父类原型上的属性和方法
    // c.message();  // 无法继承父类原型上的属性和方法

    // function Parent() {
    //     this.house = "恒大房子";
    //     this.car = "大众cc";
    //     this.message = function () {
    //         alert("哈哈哈哈");
    //     }
    // }
    // Parent.prototype.sex = "男";
    // Parent.prototype.work = function () {
    //     alert("我是做IT的");
    // }
    // let p = new Parent();

    // function Child() {
    //     Parent.call(this);
    // }
    // let c = new Child();
    // console.log(c.house);
    // console.log(c.car);
    // console.log(c.sex);  // 无法继承父类原型上的属性和方法
    // c.message();  // 无法继承父类原型上的属性和方法




    // 5.原型链继承   // 在实例化子类时无法给父类传参

    // function Parent(){
    //     this.name="jack";
    //     this.age=100;
    //     this.message=function(){
    //         alert("hello world");
    //     }
    // }
    // Parent.prototype.sex="男";
    // Parent.prototype.getUser=function(){
    //     alert(this.name+this.age+this.sex);
    // }
    // let p = new Parent();
    // function Child(){
    //     Parent.call(this);
    // }
    // Child.prototype=new Parent();
    // let c = new Child();
    // console.log(c.name);
    // console.log(c.age);
    // console.log(c.sex);
    // c.message();
    // c.getUser();

    // function Parent(){
    //     this.name="jack";
    //     this.age=100;
    //     this.message=function(){
    //         alert("hello world");
    //     }
    // }
    // Parent.prototype.sex="男";
    // Parent.prototype.getUser=function(){
    //     alert(this.name+this.age+this.sex);
    // }
    // let p = new Parent();
    // function Child(){
    //     Parent.call(this);
    // }
    // Child.prototype=new Parent();
    // let c = new Child();
    // console.log(c.name);
    // console.log(c.age);
    // console.log(c.sex);
    // c.message();
    // c.getUser();

    // function Parent(){
    //     this.name="jack";
    //     this.age=100;
    //     this.message=function(){
    //         alert("hello world");
    //     }
    // }
    // Parent.prototype.sex="男";
    // Parent.prototype.getUser=function(){
    //     alert(this.name+this.age+this.sex);
    // }
    // let p = new Parent();
    // function Child(){
    //     Parent.call(this);
    // }
    // Child.prototype=new Parent();
    // let c = new Child();
    // console.log(c.name);
    // console.log(c.age);
    // console.log(c.sex);
    // c.message();
    // c.getUser();

    // function Parent(){
    //     this.name="jack";
    //     this.age=100;
    //     this.message=function(){
    //         alert("hello world");
    //     }
    // }
    // Parent.prototype.sex="男";
    // Parent.prototype.getUser=function(){
    //     alert(this.name+this.age+this.sex);
    // }
    // let p = new Parent();
    // function Child(){
    //     Parent.call(this);
    // }
    // Child.prototype=new Parent();
    // let c = new Child();
    // console.log(c.name);
    // console.log(c.age);
    // console.log(c.sex);
    // c.message();
    // c.getUser();

    // function Parent(){
    //     this.name="jack";
    //     this.age=100;
    //     this.message=function(){
    //         alert("hello world");
    //     }
    // }
    // Parent.prototype.sex="男";
    // Parent.prototype.getUser=function(){
    //     alert(this.name+this.age+this.sex);
    // }
    // let p = new Parent();
    // function Child(){
    //     Parent.call(this);
    // }
    // Child.prototype=new Parent();
    // let c = new Child();
    // console.log(c.name);
    // console.log(c.age);
    // console.log(c.sex);
    // c.message();
    // c.getUser();




    // 6.原型链 + 对象冒充  的组合继承模式

    // function Parent(name, age) {
    //     this.name = name;
    //     this.age = age;
    //     this.getInfo = function () {
    //         alert(this.name + this.age);
    //     }
    // }
    // function Child(name, age) {
    //     Parent.call(this, name, age);
    // }
    // Child.prototype = new Parent();  // Parent.prototype也可以
    // let c = new Child("李四", 100);
    // console.log(c.name);
    // console.log(c.age);
    // c.getInfo();

    // function Parent(name,age){
    //     this.name=name;
    //     this.age=age;
    //     this.getInfo=function(){
    //         alert(this.name+this.age);
    //     }
    // }
    // function Child(name,age){
    //     Parent.call(this,name,age);
    // }
    // Child.prototype=new Parent();  // Parent.prototype也可以
    // let c = new Child("李四",100);
    // console.log(c.name);
    // console.log(c.age);
    // c.getInfo();

    // function Parent (name,age){
    //     this.name=name;
    //     this.age=age;
    //     this.getInfo=function(){
    //         alert(this.name+this.age);
    //     }
    // }
    // function Child(name,age){
    //     Parent.call(this,name,age);
    // }
    // Child.prototype=new Parent();
    // let c = new Child("李四",100);
    // console.log(c.name);
    // console.log(c.age);
    // c.getInfo();

    // function Parent(name,age){
    //     this.name=name;
    //     this.age=age;
    //     this.getInfo=function(){
    //         alert(this.name+this.age);
    //     }
    // }
    // function Child(name,age){
    //     Parent.call(this,name,age);
    // }
    // Child.prototype=new Parent();
    // let c = new Child("李四",100);
    // console.log(c.name);
    // console.log(c.age);
    // c.getInfo();

    // function Parent(name,age){
    //     this.name=name;
    //     this.age=age;
    //     this.getInfo=function(){
    //         alert(this.name+this.age);
    //     }
    // }
    // function Child(name,age){
    //     Parent.call(this,name,age);
    // }
    // Child.prototype=new Parent();
    // let c = new Child("李四",100);
    // console.log(c.name);
    // console.log(c.age);
    // c.getInfo();




    // 继承的方式: 6种
    // 1.对象冒充继承 --- 无法继承父类原型上的属性和方法 --- 解决方案: 原型继承
    // 2.原型链继承 --- 实例化子类时无法给父类传参 --- 解决方案: 原型链+对象冒充的组成继承方式
    // 3.原型链 + 对象冒充的组合继承
    // 4.原型链 + 对象冒充的组合继承的另外一种方式


    // 改变函数内this的指向: call apply bind  这几个方式的区别和它的用法

    // 1.掌握另外三种继承的方式 以及 优缺点
    // 2.掌握 call apply bind 这三个方法的使用和区别

    // 另外三种继承方式

    // 原型式继承 : 
    // function Person(name){  // 给构造函数添加了参数
    //     this.name=name;
    //     this.sum=function(){
    //         alert(this.name);
    //     }
    // }
    // Person.prototype.age=10;  // 给构造函数添加了原型属性
    // function content(obj){
    //     function F(){}
    //     F.prototype=obj;  // 继承了传入的参数
    //     return new F();  // 返回函数对象
    // }
    // var sup=new Person();  // 拿到父类的实例
    // var sup1=content(sup);
    // console.log(sup1.age);  // 10继承了父类函数的属性



    // 寄生式继承

    // function Person(name){
    //     this.name=name;
    //     this.sum=function(){
    //         alert(this.name);
    //     }
    // }
    // Person.prototype.age=10;
    // function content(obj){
    //     function F(){}
    //     F.prototype=obj; // 继承了传入的参数
    //     return new F();  // 返回函数的对象
    // }
    // var sup =new Person();
    // // 以上是原型继承,给原型式继承再套个壳子传递参数
    // function subObject(obj){
    //     var sub=content(obj);
    //     sub.name="gar";
    //     return sub;
    // }
    // var sup2=subObject(sup);
    // // 这个函数经过声明之后就成了可增添属性的对象
    // console.log(typeof subObject);  // function
    // console.log(typeof sup2);  // object
    // console.log(sup2.name);  // "gar", 返回了sub对象,继承了sub的属性



    // 寄生组合式继承(常用)

    // function Person(name){
    //     this.name=name;
    //     this.sum=function(){
    //         alert(this.name);
    //     }
    // }
    // Person.prototype.age=10;
    // // 寄生
    // function content(obj){
    //     function F(){}
    //     F.prototype=obj;
    //     return new F();
    // }
    // // content就是F实例的另一种表示法
    // var con=content(Person.prototype);
    // // con实例(F实例)的原型继承了父类函数的原型
    // // 上述更像是原型链继承,只不过只继承了原型属性

    // // 组合
    // function Sub(){
    //     Person.call(this);  // 这个继承了父类构造函数的属性
    // }  // 解决了组合式两次调用构造函数属性的缺点
    // // 重点
    // Sub.prototype=con;  // 继承了con实例
    // con.constructor=Sub;  // 一定要修复实例
    // var sub1 = new Sub();
    // // Sub的实例就继承了构造函数属性,父类实例,con的函数属性
    // console.log(sub1.age); // 10






    // call apply bind 的用法以及区别

    // call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象，第二个参数差别就来了：

    // call 的参数是直接放进去的，第二第三第 n 个参数全都用逗号分隔，直接放到后面 obj.myFun.call(db, '成都', ... , 'string')。

    // apply 的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db, ['成都', ..., 'string'])。

    // bind 除了返回是函数以外，它 的参数和 call 一样。

    // 当然，三者的参数不限定是 string 类型，允许是各种类型，包括函数 、 object 等等！



</script>